import { createNamespace, inBrowser } from '../utils'
import { raf, cancelRaf } from '../utils/dom/raf'
import { isSameSecond, parseTimeData, parseFormat } from './utils'
import './style'
var _createNamespace = createNamespace('count-down')
var createComponent = _createNamespace[0]
var bem = _createNamespace[1]

export default createComponent({
  props: {
    millisecond: Boolean,
    time: {
      type: [Number, String],
      default: 0
    },
    format: {
      type: String,
      default: 'HH:mm:ss'
    },
    type: {
      type: String,
      default: ''
    },
    typeColor: {
      type: String,
      default: ''
    },
    autoStart: {
      type: Boolean,
      default: true
    }
  },
  data: function data() {
    return {
      remain: 0
    }
  },
  computed: {
    timeData: function timeData() {
      return parseTimeData(this.remain)
    },
    formattedTime: function formattedTime() {
      var timeString = parseFormat(this.format, this.timeData)
      if (this.type) {
        return this.timeChars(timeString)
      }
      return timeString
    },
    typeStyle: function typeStyle() {
      if (this.typeColor) {
        return {
          '--count-down-card-color': this.typeColor
        }
      }
      return null
    }
  },
  watch: {
    time: {
      immediate: true,
      handler: 'reset'
    }
  },
  activated: function activated() {
    if (this.keepAlivePaused) {
      this.counting = true
      this.keepAlivePaused = false
      this.tick()
    }
  },
  deactivated: function deactivated() {
    if (this.counting) {
      this.pause()
      this.keepAlivePaused = true
    }
  },
  beforeDestroy: function beforeDestroy() {
    this.pause()
  },
  methods: {
    // @exposed-api
    start: function start() {
      if (this.counting) {
        return
      }

      this.counting = true
      this.endTime = Date.now() + this.remain
      this.tick()
    },
    // @exposed-api
    pause: function pause() {
      this.counting = false
      cancelRaf(this.rafId)
    },
    // @exposed-api
    reset: function reset() {
      this.pause()
      this.remain = +this.time

      if (this.autoStart) {
        this.start()
      }
    },
    tick: function tick() {
      // should not start counting in server
      // see: https://github.com/youzan/vant/issues/7807
      if (!inBrowser) {
        return
      }

      if (this.millisecond) {
        this.microTick()
      } else {
        this.macroTick()
      }
    },
    microTick: function microTick() {
      var _this = this

      this.rafId = raf(function() {
        /* istanbul ignore if */
        // in case of call reset immediately after finish
        if (!_this.counting) {
          return
        }

        _this.setRemain(_this.getRemain())

        if (_this.remain > 0) {
          _this.microTick()
        }
      })
    },
    macroTick: function macroTick() {
      var _this2 = this

      this.rafId = raf(function() {
        /* istanbul ignore if */
        // in case of call reset immediately after finish
        if (!_this2.counting) {
          return
        }

        var remain = _this2.getRemain()

        if (!isSameSecond(remain, _this2.remain) || remain === 0) {
          _this2.setRemain(remain)
        }

        if (_this2.remain > 0) {
          _this2.macroTick()
        }
      })
    },
    getRemain: function getRemain() {
      return Math.max(this.endTime - Date.now(), 0)
    },
    setRemain: function setRemain(remain) {
      this.remain = remain
      this.$emit('change', this.timeData)

      if (remain === 0) {
        this.pause()
        this.$emit('finish')
      }
    },
    timeChars(str) {
      return str.match(/(\d+|[^\d]+)/g)
    },
    formatTimeData(h) {
      var time = this.formattedTime
      if (Array.isArray(time)) {
        return time.map(str => {
          var className = this.type + (/^\d+$/.test(str) ? '-block' : '-split')
          return h(
            'div',
            {
              class: bem(className)
            },
            str
          )
        })
      }
      return time
    }
  },
  render: function render() {
    var h = arguments[0]
    return h(
      'div',
      {
        class: bem([this.type]),
        style: this.typeStyle
      },
      [this.slots('default', this.timeData) || this.formatTimeData(h)]
    )
  }
})
